﻿package {
	import flash.display.Sprite;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.events.MouseEvent;
	import flash.text.TextField;
	import fl.controls.Button;
	import flash.display.MovieClip;
	import flash.display.Shape;
	import flash.geom.Point;
	import flash.text.engine.EastAsianJustifier;


	public class Scenary extends Sprite {
		public static const DEBUG = true;
		public static const HEIGHT = 600;
		public static const WIDTH = 950;

		public var turn:Number = 1;   //TODO: fixme, encapsulate like currentUser.cannon?
		public var objectList:Object;//Associative Array
		public var terrain:Shape;

		private static var inst:Scenary; // Singleton Scenary
		
		/** Singlenton implementation.
			@return Scenary of the game */
		public static function getInstance() : Scenary { 
			return inst;
		}

		public function Scenary() {
			inst = this;
			objectList = new Object();
			init();
		}
		
		private function init():void {
			stage.frameRate = 24;

			buildScenary();
			initControls();
			objectList.explosions = new Array();
		}

		private function buildScenary() {
			drawRandomTerrain();
			
			objectList.cannon1 = createCannon(false);
			objectList.cannon2 = createCannon(true);

			addChild(objectList.cannon1);
			addChild(objectList.cannon2);
			/*for (var key:Object in objectList) {
				addChild(objectList[key]);
			}*/
			drawTrees();
		}
		
		private function createCannon(player:Boolean):Cannon {
			var posX, posY, i:int;
			
			i = Number(player);
			posX = WIDTH * i + Math.pow(-1, i) * (Math.random() * WIDTH / 3 + Cannon.CANNON_WIDTH);
			posY = HEIGHT - (90 + Cannon.CANNON_HEIGHT); //TODO when scenary has no controls
			
			var c:Cannon = new Cannon(posX, posY, player);
			var botLeft:Point  = new Point(posX, posY + Cannon.CANNON_HEIGHT );
			var botRight:Point = new Point(posX + Cannon.CANNON_WIDTH, c.y + Cannon.CANNON_HEIGHT);

			while(this.getObjectsUnderPoint(botLeft).length > 0 ||
				  this.getObjectsUnderPoint(botRight).length > 0) {
				  botLeft.y  -= 1;
				  botRight.y -= 1;
			}
			c.y = botLeft.y - Cannon.CANNON_HEIGHT;
			
			if(Scenary.DEBUG) {
				drawXatPoint(botLeft.x, botLeft.y);
				drawXatPoint(botRight.x, botRight.y);
			}
		
			//Draw a support to the cannon in the Terrain //TODO add to the terrain BitMap
			var supHeight:Number = Scenary.HEIGHT - (botLeft.y + 90);
			var cSupport:Shape = new Shape;
			cSupport.graphics.beginFill(0x000000);
			cSupport.graphics.drawRect(botLeft.x, botLeft.y, Cannon.CANNON_WIDTH, supHeight);
			cSupport.graphics.endFill();
			addChild(cSupport);
			
			return c;
		}
		
		private function drawTrees():void {
			objectList.trees = new Array();
			var t:Tree = new Tree(330, getTerrainY(330));
			this.drawXatPoint(330, getTerrainY(330) - 77);
			objectList.trees.push(t);
			addChild(t);
		}
		private function getTerrainY(x:Number):Number {
			var p:Point = new Point(x, Scenary.HEIGHT - 90);
			while(this.getObjectsUnderPoint(p).length > 0) {
				p.y -= 1;
			}
			return p.y;
		}

		private function initControls() {
			power1.minimum = Cannon.POWER_MIN;
			power1.maximum = Cannon.POWER_MAX;
			power1.value = objectList.cannon1.getPower();
			power1.textField.editable = false;
			
			power2.enabled = false;
			power2.minimum = Cannon.POWER_MIN;
			power2.maximum = Cannon.POWER_MAX;
			power2.value = objectList.cannon2.getPower();
			power2.textField.editable = false;
			
			angle1.minimum = Cannon.ANGLE_MIN;
			angle1.maximum = Cannon.ANGLE_MAX;
			angle1.value = objectList.cannon1.getAngle();
			angle1.textField.editable = false;
			
			angle2.enabled = false;
			angle2.minimum = Cannon.ANGLE_MIN;
			angle2.maximum = Cannon.ANGLE_MAX;
			angle2.value = objectList.cannon2.getAngle();
			angle2.textField.editable = false;

			angle1.addEventListener(Event.CHANGE, updateAngle);
			angle2.addEventListener(Event.CHANGE, updateAngle);
			
			power1.addEventListener(Event.CHANGE, updatePower);
			power2.addEventListener(Event.CHANGE, updatePower);

			btn_fire.addEventListener(MouseEvent.CLICK, shootCannon);
		}

		/** Create a random terrain */
		private function drawRandomTerrain() {
			terrain = new Shape();
			addChild(terrain);
 
			terrain.graphics.lineStyle(1);
			terrain.graphics.beginFill(0);
			// Start drawing
			terrain.graphics.moveTo(0, 400);
			// Random draw
			for(var i:int=1; i<=10; i++) {
				var nextX:int = i * WIDTH/10;
				var nextY:int = 200 + Math.random()*(HEIGHT-290); //margin-top:200px
				terrain.graphics.lineTo(nextX, nextY);
			}
			terrain.graphics.lineTo(WIDTH, 400);
			//Close de scenary
			terrain.graphics.lineTo(WIDTH, HEIGHT - 90); //margin-bottom:90px
			terrain.graphics.lineTo(0, HEIGHT - 90);
			terrain.graphics.endFill();
		}
		
		public function updateListeners():void {
			var player:Boolean = false;
			//btn_fire.addEventListener(MouseEvent.CLICK, shootCannon);
			btn_fire.enabled = true;
			
			// Change the turn
			turn = turn % 2 + 1;
			if(turn == 1) player = true;
			
			power1.enabled = player;
			power2.enabled = !player;
			angle1.enabled = player;
			angle2.enabled = !player;
		}
		private function shootCannon(e:Event):void {
			new Event("shoot");
			updateAngle(null);
			updatePower(null);
			var cannon:Cannon = objectList["cannon" + this.turn];
			addChild(cannon.shootBall());
			//btn_fire.removeEventListener(MouseEvent.CLICK, shootCannon);
			btn_fire.enabled = false;
		}

		private function updateAngle(e:Event):void {
			if(this.turn == 1) {
				objectList.cannon1.setAngle(angle1.value);
			} else {
				objectList.cannon2.setAngle(angle2.value);
			}
		}
		
		private function updatePower(e:Event):void {
			if(this.turn == 1) {
				objectList.cannon1.setPower(power1.value);
			} else {
				objectList.cannon2.setPower(power2.value);
			}
		}

		/** DEBUG PURPOSES **/
		public function drawXatPoint(x:Number, y:Number):void {
			var deb = new Shape();
			addChild(deb);
			deb.graphics.lineStyle(1, 0xff0000);
			deb.graphics.moveTo(x, y - 5);
			deb.graphics.lineTo(x, y + 5);
			
			var seb = new Shape();
			addChild(seb);
			seb.graphics.lineStyle(1, 0xff0000);
			seb.graphics.moveTo(x - 5, y);
			seb.graphics.lineTo(x + 5, y);
		}
	}
}